package com.example.demo.controller;

import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.AppUtil.BaseActionUtil;
import com.example.demo.AppUtil.CharUtil;
import com.example.demo.AppUtil.FullUserInfo;
import com.example.demo.config.LocalDateTimeFormatConfig;
import com.example.demo.entity.DTO.UserLoginByWeChatDTO;
import com.example.demo.entity.User;
import com.example.demo.entity.VO.UsersLoginByWeChatVO;
import com.example.demo.result.MyPage;
import com.example.demo.result.Result;
import com.example.demo.service.IAnTokenService;
import com.example.demo.service.WeixinMaService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.qiniu.util.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;

import com.example.demo.service.IUsersService;
import com.example.demo.entity.Users;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @author Mr.we
 * @since 2024-05-28
 */
@Api(tags = "红-用户接口")
@RestController
@RequestMapping("/auth")
@Slf4j
public class UsersController extends BaseActionUtil {

    @Autowired
    private IUsersService usersService;
    @Resource
    private WeixinMaService weixinMaService;
    @Resource
    LocalDateTimeFormatConfig localDateTimeFormatConfig;
    @Autowired
    private IAnTokenService anTokenService;



    /**
     * 微信小程序登录
     * @param usersLoginByWeChatVO 用户登录信息
     * @return 用户信息
     */
    @ApiOperationSupport(author = "Mr.we")
    @ApiOperation(value = "微信小程序登录")
    @PostMapping("/login/wechat2")
    public Result<UserLoginByWeChatDTO> wechatLogin(@Valid UsersLoginByWeChatVO usersLoginByWeChatVO) {
        // 将前端传来的VO对象转换为实体对象
        Users users = new Users();
        // 将VO对象中的数据复制到实体对象中
        BeanUtil.copyProperties(usersLoginByWeChatVO,users);
        //将查询的用户存入登录
        UserLoginByWeChatDTO login = usersService.wechatLogin(users);
        //保存登录信息
        if (login.getToken() != null){
            log.info("登录成功"+login);
            StpUtil.login(login.getUserId());
            //获取当前会话ToKen
            String token = StpUtil.getTokenValue();
            //设置ToKen
            login.setToken(token);
        }
        //返回结果
        return Result.success(login).msg("登录成功");
    }

    @ApiOperation(value = "网页注册")
    @ApiOperationSupport(author = "力铉器")
    @PostMapping("/register")
    public Result<Users> register(@Valid @RequestBody Users users) {
        boolean result = usersService.register(users);
        if (!result){
            return Result.error().msg("注册失败");
        }
        return Result.success().msg("注册成功");
    }


      //查询所有接口
      @ApiOperationSupport(author = "Mr.Yang")
    @ApiOperation(value = "查询用户表所有数据")
    @GetMapping("/login")
      public Result<List<Users>> findAll() {
          return Result.success(usersService.list()).msg("查询成功");
      }




//根据id查询数据接口
    @ApiOperationSupport(author = "Mr.Yang")
    @ApiOperation(value = "根据id查询数据接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id",value = "组件id",required = true)
    })
    @GetMapping("/login/{id}")
    public Result<Users> findOne(@PathVariable Integer id) {
        return Result.success(usersService.getById(id)).msg("查询成功");
    }


      /**分页查询接口
      @param pageNum
     * @param pageSize
     * @return
    */
    @ApiOperationSupport(author = "Mr.Yang")
    @ApiOperation(value = "分页查询接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum",value = "页码",example="1",required = true),
            @ApiImplicitParam(name = "pageSize",value = "每页多少条",example="10",required = true)
    })
    @GetMapping("/page")
    public Result<MyPage<User>> findPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        return Result.success().data(usersService.page(new Page<>(pageNum, pageSize), queryWrapper)).msg("查询成功");
    }

    /**
      更新接口
      @param
     * @return
     */
    @ApiOperationSupport(author = "Mr.Yang")
    @ApiOperation(value = "用户更新信息接口")
    @PostMapping
    public Result<String> save(@RequestBody Users users) {
        usersService.saveOrUpdate(users);
        return Result.success().msg("更新成功");
    }

    /**删除接口
      @param id
     * @return
    */
    @ApiOperationSupport(author = "Mr.Yang")
    @ApiOperation(value = "删除用户接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id",value = "组件id",required = true)
    })
    @DeleteMapping("/{id}")
    public Result<String> delete(@PathVariable Integer id) {
        usersService.removeById(id);
        return Result.success().msg("删除成功");
    }

    /**
      批量删除接口
      @param ids
     * @return
    */
    @ApiOperationSupport(author = "Mr.Yang")
    @ApiOperation(value = "批量删除接口")
    @PostMapping("/del/batch")
    public Result<String> deleteBatch(@RequestBody List<Integer> ids) {
        usersService.removeByIds(ids);
        return Result.success().msg("批量删除成功");
    }
    /**
     * 微信静默登录
     */
    @GetMapping("/{code}")
    @ApiOperation(value = "微信静默登录", notes = "使用code静默登录")
    public Object loginByCode(@PathVariable String code) {
        weixinMaService.init();
        @Valid
        UsersLoginByWeChatVO userVo = new UsersLoginByWeChatVO();
        userVo.setCode(code);
        log.info("code:{}", userVo.getCode());
        try {
            WxMaJscode2SessionResult session = weixinMaService.getUserService().getSessionInfo(userVo.getCode());

            String openid = session.getOpenid();
            log.info("openid:{}", openid);

            Date nowTime = new Date();
            //接收用户信息
            User user = new Users();
            BeanUtil.copyProperties(userVo, user);
            if (userVo.getCode() != null){
                String name = "微信用户" + UUID.randomUUID();
                user.setUserName(name);
                user.setOpenId(openid);
                user.setPassword(openid);
                user.setCreateTime(localDateTimeFormatConfig.convertDateToLocalDateTime(nowTime));
                User users = usersService.findUserByOpenId(user.getOpenId());
                if( users == null){
                    usersService.saveUser(user);
                }
            }
            //查询用户信息
            User users = usersService.findUserByOpenId(user.getOpenId());
            log.info("用户信息：{}", users);
                Map<String, Object> tokenMap = anTokenService.createToken(users.getUserId());
                String token = MapUtils.getString(tokenMap, "token");

            if (StringUtils.isNullOrEmpty(token)) {
                return Result.error("登录失败");
            }

            Map<String, Object> resultObj = new HashMap<>();
            resultObj.put("token", token);
            resultObj.put("userInfo", userVo);
            resultObj.put("userId", userVo.getUserId());
            return Result.success().msg("登陆成功").data(resultObj);
        } catch (WxErrorException e) {
            log.error("登录失败", e);
            return Result.error("登录失败：").data(e.getError().getErrorCode() );
        }
    }
    /**
     * 微信小程序登录
     */
    @ApiOperationSupport(author = "Mr.we")
    @ApiOperation(value = "微信小程序登录")
    @PostMapping("/login/wechat")
    public Map<String, Object> WechatLogin() {
        JSONObject jsonParam = this.getJsonRequest();
        FullUserInfo fullUserInfo = null;
        String code = "";
        if (!StringUtils.isNullOrEmpty(jsonParam.getString("code"))) {
            code = jsonParam.getString("code");
        }
        if (null != jsonParam.get("userInfo")) {
            fullUserInfo = jsonParam.getObject("userInfo", FullUserInfo.class);
        }
        if (null == fullUserInfo) {
            return toResponseFail("登录失败");
        }

        Map<String, Object> resultObj = new HashMap<String, Object>();
        User userInfo = fullUserInfo.getUserInfo();

        try{
            WxMaJscode2SessionResult session = weixinMaService.getUserService().getSessionInfo(code);
            // 用户信息校验
            log.info("》》》微信返回sessionData：" + session.toString());

            if (!weixinMaService.getUserService().checkUserInfo(session.getSessionKey(), fullUserInfo.getRawData(), fullUserInfo.getSignature())) {
                log.error("登录失败：数据签名验证失败");
                return toResponseFail("登录失败");
            }

            // 解密用户信息
            WxMaUserInfo wxMpUser = weixinMaService.getUserService().getUserInfo(session.getSessionKey(), fullUserInfo.getEncryptedData(), fullUserInfo.getIv());
            log.info("》》》解密用户信息：" + wxMpUser.toString());

            Date nowTime = new Date();
            @Valid
            UsersLoginByWeChatVO userVo = new UsersLoginByWeChatVO();
            userVo.setOpenId(session.getOpenid());
            //获取用户信息(要一个通过搜索openid得到用户信息)
            BeanUtil.copyProperties(userInfo, userVo);
            User users = usersService.findUserByOpenId(session.getOpenid());
            userVo.setUserId(users.getUserId());
            if (null == users){
                User userOne = new User();
                String name = "微信用户" + CharUtil.getRandomString(12);
                userOne.setNickname(name);
                userOne.setOpenId(userVo.getOpenId());
                userOne.setPassword(userVo.getOpenId());
                userOne.setUserName(name);
                userOne.setOpenId(userVo.getOpenId());
                userOne.setHeadImg(userVo.getUserHeaderimg());
                userOne.setCreateTime(localDateTimeFormatConfig.convertDateToLocalDateTime(nowTime));
                usersService.saveUser(userOne);
            }else{
                users.setUpdateTime(localDateTimeFormatConfig.convertDateToLocalDateTime(nowTime));
                usersService.updateById(users);
            }

            Map<String, Object> tokenMap = anTokenService.createToken(userVo.getUserId());
            String token = MapUtils.getString(tokenMap, "token");

            if (StringUtils.isNullOrEmpty(token)) {
                return toResponseFail("登录失败");
            }

            resultObj.put("token", token);
            resultObj.put("userInfo", userVo);
            resultObj.put("userId", userVo.getUserId());
            return toResponseSuccess(resultObj);

        } catch (Exception e) {
            log.error("登录失败", e);
            return toResponseFail("登录失败");
        }
    }
}